package ca.starfarer.kobold.dao.sqlite;

import ca.starfarer.kobold.model.Alignment;
import ca.starfarer.kobold.model.Monster;
import ca.starfarer.kobold.dao.DataAccessException;
import ca.starfarer.kobold.dao.MonsterDAO;

import java.sql.*;

/**
 * @author Kevin
 */
class MonsterDAOImpl implements MonsterDAO {

    private static final String TABLE_NAME = "Monsters";

    private static final String NAME = "Name";
    private static final String MAX_HIT_POINTS = "MaxHitPoints";
    private static final String HIT_POINTS = "HitPoints";
    private static final String ALIGNMENT = "Alignment";

    private static String[] columnNames = { NAME, MAX_HIT_POINTS, HIT_POINTS, ALIGNMENT };
    
    private final SQLiteDAOManager manager;

    MonsterDAOImpl(SQLiteDAOManager manager) {
        this.manager = manager;
    }

    void createTable() throws SQLException {
        Statement statement = manager.getConnection().createStatement();
        try {
            Helper.dropTable(statement, TABLE_NAME);
            Helper.createTable(statement, TABLE_NAME, columnNames);
        }
        finally {
            statement.close();
        }
    }

    public Monster get(Long id) throws DataAccessException {
        try {
            Monster result = null;

            Statement statement = manager.getConnection().createStatement();
            try {
                ResultSet resultSet = statement.executeQuery("select * from Monsters where Id = " + id);
                if (resultSet.next()) {
                    result = new Monster();
                    result.setId(id);
                    result.setName(resultSet.getString(NAME));
                    result.setMaxHitPoints((Integer) resultSet.getObject(MAX_HIT_POINTS));
                    result.setHitPoints((Integer) resultSet.getObject(HIT_POINTS));
                    result.setAlignment(Alignment.valueOf(resultSet.getString(ALIGNMENT)));
                }
            }
            finally {
                statement.close();
            }

            return result;
        } catch (SQLException e) {
            throw new DataAccessException("Cannot retrieve Monster by Id", e);
        }
    }

    public void save(Monster monster) throws DataAccessException {
        if (monster.getId() == null) {
            insert(monster);
        }
        else {
            update(monster);
        }
    }

    private void insert(Monster monster) throws DataAccessException {
        try {
            Statement statement = manager.getConnection().createStatement();
            try {
                Long id = Helper.insert(statement, TABLE_NAME, columnNames, monster.getName(), monster.getMaxHitPoints(), monster.getHitPoints(), monster.getAlignment().name());
                monster.setId(id);
            }
            finally {
                statement.close();
            }
        }
        catch (SQLException e) {
            throw new DataAccessException("Cannot insert new Monster", e);
        }
    }

    private void update(Monster monster) throws DataAccessException {
        try {
            Statement statement = manager.getConnection().createStatement();
            try {
                Helper.update(statement, TABLE_NAME, columnNames, monster.getId(), monster.getName(), monster.getMaxHitPoints(), monster.getHitPoints(), monster.getAlignment().name());
            }
            finally {
                statement.close();
            }
        }
        catch (SQLException e) {
            throw new DataAccessException("Cannot update Monster", e);
        }
    }
}
